package base2dev.core.common.dal.imp;

import java.util.ArrayList;
import java.util.List;


public class Query<T> implements base2dev.core.common.dal.Query<T> {

	private Class<T> clazz;
	private String from = " from %1$s ";
	private String alias = "a"; 
	private String where = " where 1=1 ";
	private String join;  
	private int MAX_ROWS = 50;
	private int page = 0;
	
 	public Query<T> select(Class<T> type) {
		clazz =   type ;
		from = String.format(from, clazz.getName());
		return this;
	}

	public Query join(String join) {
		this.join = " " + join;
		return this;
	}

	public Query where(String condition, Object parameter) {
 
		this.where += " and " + String.format(condition, parameter); 
		return this;
	}

	public String get() {

		return from + where;
	}

}


/*
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Accendra.AFC.Common.Reflection;
using LeaderSearch.Support.Exceptions;
using LeaderSearch.Support.Seeking;
using NHibernate;
using NHibernate.Impl;

namespace LeaderSearch.Support.NHibernate
{
    public class Select
    {
        protected string alias;
        protected Type type;
        protected List<string> expressions;
        private readonly JoinBuilder joinBuilder;
        protected Dictionary<string, object> parameters;
        protected Dictionary<string, ICollection> parameterList;
        protected List<string> orders;
        protected List<string> selectExpressions;
        private GroupBuilder groupBuilder;
        protected bool distinct;
        private int maxResults = -1;
        private readonly List<string> projections;
        private bool random;

        public IDictionary<string, object> Parameters
        {
            get { return parameters; }
        }

        public IDictionary<string, ICollection> ParameterList
        {
            get { return parameterList; }
        }

        public static Select From<T>()
        {
            return new Select(typeof(T));
        }

        public Select NowFrom<T>()
        {
            type = typeof(T);
            return this;
        }

        protected Select(Type type)
        {
            alias = "t";
            this.type = type;
            expressions = new List<string>();
            projections = new List<string>();
            groupBuilder = new GroupBuilder(alias);
            parameters = new Dictionary<string, object>();
            parameterList = new Dictionary<string, ICollection>();
            orders = new List<string>();
            joinBuilder = new JoinBuilder(alias);
            distinct = false;
        }

        public Select SetAlias(string newAlias)
        {
            alias = newAlias;
            joinBuilder.ChangeAlias(newAlias);
            groupBuilder.ChangeAlias(newAlias);
            return this;
        }

        public Select Distinct()
        {
            distinct = true;
            return this;
        }

        public Select Having(string expression)
        {
            return Having(expression, false);
        }

        public Select Having(string expression, bool withOutAlias)
        {
            groupBuilder.AddHaving(withOutAlias ? expression : string.Format("{0}.{1}", alias, expression));
            return this;
        }

        public Select GroupBy(string expression)
        {
            return GroupBy(expression, false);
        }

        public Select GroupBy(string expression, bool withOutAlias)
        {
            groupBuilder.AddGroupBy(withOutAlias ? expression : string.Format("{0}.{1}", alias, expression));
            return this;
        }

        public Select OrderRandom()
        {
            random = true;
            return this;
        }

        public Select Where(string expression)
        {
            var formattedExpression = expression;

            if (!expressions.Contains(formattedExpression))
                expressions.Add(formattedExpression);

            return this;
        }

        public Select Where(string expression, IQueryBased query, string subQueryAlias)
        {
            Where(expression.Replace("{subQuery}", query.GiveMeTheQuery(subQueryAlias, this).Hql));
            return this;
        }

        public Select Like(object value, params string[] properties)
        {
            var parameter = string.Concat(string.Join("_", properties).Replace(".", "_"), "_like");

            return Where(string.Format("{0} like :{1}", properties.Concatenated(), parameter)).SetParameter(parameter, value);
        }

        public Select Between(string property, object start, object end)
        {
            var startParameter = string.Concat(property.Replace(".", "_"), "_start");
            var endParameter = string.Concat(property.Replace(".", "_"), "_end");

            if (start != null && end != null)
                Where(string.Format("{0} between :{1} and :{2}", property, startParameter, endParameter))
                    .SetParameter(startParameter, start)
                    .SetParameter(endParameter, end);
            else if (start != null)
                Where(string.Format("{0} >= :{1}", property, startParameter))
                    .SetParameter(startParameter, start);
            else if (end != null)
                Where(string.Format("{0} <= :{1}", property, endParameter))
                    .SetParameter(endParameter, end);
            return this;
        }

        public Select Between(string property, DateTime? start, DateTime? end)
        {
            object startDate = null;
            object endDate = null;

            if (start.HasValue)
                startDate = start.Value.From();

            if (end.HasValue)
                endDate = end.Value.To();

            return Between(property, startDate, endDate);
        }

        private string Format(string expression)
        {
            return expression.Replace("{alias}", alias);
        }

        public Select Join(string property)
        {
            joinBuilder.Add(property);
            return this;
        }

        public Select FetchJoin(string property)
        {
            joinBuilder.AddFetch(property);
            return this;
        }

        public Select FetchLeftJoin(string property)
        {
            joinBuilder.AddLeftFetch(property);
            return this;
        }

        public Select LeftJoin(string property)
        {
            joinBuilder.AddLeft(property);
            return this;
        }

        public Select OrderBy(string order)
        {
            if (!orders.Contains(order)) orders.Add(order);
            return this;
        }

        public Select MaxResults(int max)
        {
            maxResults = max;
            return this;
        }

        public DetachedQuery Query()
        {
            var select = string.Format("select {0} ", (distinct) ? "distinct" : string.Empty);
            select = projections.IsNotEmpty() ? select.Concatenate(projections.Join(", ")) : select.Concatenate(alias);

            var from = string.Format("{0} from {2} {1}", select, alias, EntityName);

            from = string.Format("{0} {1}", from, joinBuilder);

            var where = string.Empty;

            if (expressions.IsNotEmpty())
                where = string.Format("where {0}", string.Join(" and ",
                    expressions.Select(x => string.Format("({0})", x)).ToArray()));

            var orderby = string.Empty;
            if (orders.Count > 0)
                orderby = string.Format("order by {0}", string.Join(", ", orders.ToArray()));

            var groupExpression = groupBuilder.ToString();

            //TODO: Esto ordena por una columna 1 a (cant de propiedades) , Buscar la forma de hacer un orden random de verdad =P
            if (random)
                orderby = string.Empty;// = "order by {0}".FormatWith(new Random().Next(type.GetProperties().Count()));

            var squery = Format(string.Format("{0} {1} {2} {3}", from, where, groupExpression, orderby)).Trim();

            var query = new DetachedQuery(squery);

            foreach (var parameter in parameters)
            {
                query.SetParameter(Format(parameter.Key), parameter.Value);
            }

            foreach (var parameter in parameterList)
            {
                query.SetParameterList(Format(parameter.Key), parameter.Value);
            }

            query.SetMaxResults(maxResults);

            return query;
        }



        public Select SetParameter(string key, object value)
        {
            if (!parameters.ContainsKey(key)) parameters.Add(key, value);

            return this;
        }

        public Select SetParameterList<Type>(string key, ICollection<Type> value)
        {
            if (!parameterList.ContainsKey(key)) parameterList.Add(key, (ICollection)value);

            return this;
        }

        public Select SetParameterList(string key, ICollection value)
        {
            if (!parameterList.ContainsKey(key)) parameterList.Add(key, value);

            return this;
        }

        public Select Projection(params string[] projection)
        {
            Projection(false, projection);
            return this;
        }

        public Select Projection(bool withOutAlias, params string[] projection)
        {
            projection.ForEach(x => projections.Add(withOutAlias ? x : string.Format("{{alias}}.{0}", x)));
            return this;
        }

        public DetachedQuery ProjectedQuery(params string[] projections)
        {
            return Projection(projections).Query();
        }

        private string EntityName
        {
            get { return IsImportType ? type.Name : type.FullName; }
        }

        private bool IsImportType
        {
            get { return type.IsInterface; }
        }

        private class GroupBuilder
        {
            private readonly List<string> havingExpressions = new List<string>();
            private readonly List<string> groupByExpressions = new List<string>();
            private string Alias { get; set; }

            public GroupBuilder(string alias)
            {
                Alias = alias;
            }

            public GroupBuilder ChangeAlias(string alias)
            {
                Alias = alias;
                return this;
            }

            public GroupBuilder AddHaving(string expression)
            {
                havingExpressions.Add(expression);
                return this;
            }

            public GroupBuilder AddGroupBy(string expression)
            {
                groupByExpressions.Add(expression);
                return this;
            }

            private string GenerateHaving()
            {
                if (havingExpressions.IsEmpty())
                    return string.Empty;

                if (groupByExpressions.IsEmpty())
                    throw new HavingMustHaveAGroupByExpresionException("Having  must have group by expresion");

                var having = new StringBuilder("having ");
                having.Append(string.Join(" and ", havingExpressions.ToArray()));
                return having.ToString();
            }

            private string GenerateGroupBy()
            {
                if (groupByExpressions.IsEmpty())
                    return string.Empty;

                var groupBy = new StringBuilder("group by ");
                groupBy.Append(string.Join(", ", groupByExpressions.ToArray()));
                return groupBy.ToString();
            }

            public override string ToString()
            {
                return string.Format("{0} {1}", GenerateGroupBy(), GenerateHaving()).Replace("{alias}", Alias).Trim();
            }
        }

        private class JoinBuilder
        {
            private readonly Dictionary<string, string> joins = new Dictionary<string, string>();
            private readonly Dictionary<string, string> leftjoins = new Dictionary<string, string>();
            private readonly Dictionary<string, string> fetchJoins = new Dictionary<string, string>();
            private readonly Dictionary<string, string> fetchLeftoins = new Dictionary<string, string>();
            private string Alias { get; set; }

            public JoinBuilder(string alias)
            {
                Alias = alias;
            }

            public JoinBuilder ChangeAlias(string alias)
            {
                Alias = alias;
                return this;
            }

            public JoinBuilder Add(string property)
            {
                if (!joins.ContainsKey(property)) joins.Add(property, property);
                return this;
            }

            public JoinBuilder AddLeft(string property)
            {
                if (!leftjoins.ContainsKey(property)) leftjoins.Add(property, property);
                return this;
            }

            public JoinBuilder AddFetch(string property)
            {
                if (!fetchJoins.ContainsKey(property)) fetchJoins.Add(property, property);
                return this;
            }

            public JoinBuilder AddLeftFetch(string property)
            {
                if (!fetchLeftoins.ContainsKey(property)) fetchLeftoins.Add(property, property);
                return this;
            }

            public override string ToString()
            {
                var result = new StringBuilder();
                joins.ForEach(x => result.AppendFormat(" join {0}.{1} ", Alias, x.Value));
                leftjoins.ForEach(x => result.AppendFormat(" left join {0}.{1} ", Alias, x.Value));
                fetchJoins.ForEach(x => result.AppendFormat(" join fetch {0}.{1} ", Alias, x.Value));
                fetchLeftoins.ForEach(x => result.AppendFormat(" left join fetch {0}.{1} ", Alias, x.Value));
                return result.ToString().Trim();
            }
        }
    }

    public class HavingMustHaveAGroupByExpresionException : StrangerThingsHaveHappened
    {
        public HavingMustHaveAGroupByExpresionException(string message)
            : base(message)
        {
        }
    }

    public class SelectFrom<T> where T : class, IIdentifiable
    {
        private readonly Select select;

        public SelectFrom()
        {
            select = Select.From<T>();
        }

        private static string ParameterNameOf(string propertyName)
        {
            return string.Concat(propertyName.Replace(".", "_"), "_value");
        }

        public SelectFrom<T> Where<U>(Expression<Func<T, U>> expression, IWhereComparison comparison)
        {
            var propertyName = expression.MemberExpression().ToString();
            propertyName = propertyName.Substring(propertyName.IndexOf(".") + 1);

            var parameterName = ParameterNameOf(propertyName);

            comparison.ApplyTo(select, propertyName, parameterName);

            return this;
        }

        public IQuery ExecuteIn(ISession session)
        {
            return select.Query().GetExecutableQuery(session);
        }

        public override string ToString()
        {
            return select.Query().Hql;
        }

    }

    public interface IWhereComparison
    {
        void ApplyTo(Select select, string propertyName, string parameterName);
    }

    public class Is
    {
        public static IWhereComparison EqualTo<T>(T value)
        {
            return new EqualityTo<T>(value);
        }

        private class EqualityTo<T> : IWhereComparison
        {
            private readonly T value;

            public EqualityTo(T value)
            {
                this.value = value;
            }

            public void ApplyTo(Select select, string propertyName, string parameterName)
            {
                select.Where(string.Format("{{alias}}.{0} = :{1}", propertyName, parameterName))
                .SetParameter(parameterName, value);
            }
        }
    }
}
*/